﻿using Ivony.Html;
using Ivony.Html.Parser;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using CGT.Infrastructure.Entity;
using CGT.Infrastructure.Service;
using CGT.Infrastructure.Repository;
using System.Threading.Tasks;

namespace ConsoleTest
{
    public class ProcessCarInfo
    {
        string logBaseDic = @"C:\cn357Log";
        string dbLogPath = @"C:\cn357Log\dbError.txt";//批量入库catch
        string tempLogPath = @"C:\cn357Log\tempError.txt";//解析html报错catch
        string path = @"C:\CN";//基础文件目录 
        public void Excute()
        {
            Scan(path);
        }
        /// <summary>
        /// 获取目录下所有子文件夹内文件
        /// </summary>
        /// <returns></returns>
        public void Scan(string path = @"C:\cn357CarSeries")
        {
            var filePathList = new List<CarInfoFileModel>();
            DirectoryInfo theFolder = new DirectoryInfo(path);
            var carService = new CN357_CarInfoService();
            var enService = new CN357_EngineInfoService();
            //子文件夹
            foreach (DirectoryInfo NextFolder in theFolder.GetDirectories())
            {
                Console.WriteLine(string.Format("INFO: {0} : {1} 文件夹开始执行 ", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"), NextFolder.Name));
                System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
                watch.Start();//开始计时
                //遍历每个子文件夹下的文件
                FileInfo[] fileInfo = NextFolder.GetFiles();
                var carInfoList = new List<CN357_CarInfo>();
                var engineList = new List<CN357_EngineInfo>();
                foreach (FileInfo NextFile in fileInfo)
                {
                    try
                    {
                        //根据fullName（整体绝对路径） 获取解析模版
                        var dom = GetProxyHtml(NextFile.FullName);
                        Cars cars = GetCarsByHtml(dom);
                        var carInfo = cars.CarInfo;
                        var engineInfo = cars.EngineInfo;
                        //通过文件名确定发动机信息和车辆信息是同一条数据
                        carInfo.RealCode = NextFile.Name;
                        engineInfo.RealCode = NextFile.Name;
                        carInfoList.Add(carInfo);
                        engineList.Add(engineInfo);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(string.Format("TEMP_ERROR: {0} : 文件{1}解析异常报错，catch错误信息：{2} ", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"), NextFile.FullName, ex.Message));
                        //单条错误记日志，记录错误文件，单独读
                        var message = NextFile.FullName + "|" + ex.Message;
                        WriteLog(1, message);
                    }
                }
                try
                {
                    //同文件夹下所有文件解析数据批量入库
                    carService.Insert(carInfoList);
                    enService.Insert(engineList);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(string.Format("DB_ERROR: {0} : 文件夹{1}数据批量入库异常报错，catch错误信息：{2} ", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"), NextFolder.Name, ex.Message));
                    //批量入库记录日志，记录批次(文件夹名)
                    var message = NextFolder.FullName + "|" + ex.Message;
                    WriteLog(2, message);
                }
                foreach (FileInfo file in NextFolder.GetFiles())
                {
                    //转移文件
                    MoveDirFile(file.FullName);
                }
                watch.Stop();
                Console.WriteLine(string.Format("INFO : {0} : {1} 文件夹成功结束执行，共耗时{2}毫秒, carinfo共{3}条，engine共{4}条", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"), NextFolder.Name, watch.ElapsedMilliseconds, carInfoList.Count, engineList.Count));
            }

            //10分钟一次递归调用自己，持续执行
            Thread.Sleep(600000);
            Excute();
        }
        /// <summary>    
        /// 移动目录内的文件到另一目录    
        /// </summary>    
        /// <param name="sorDir">源目录,如:Server.MapPath("~/product_image/44/8813/")</param>    
        /// <param name="desDir">目标目录,如:Server.MapPath("~/product_image/141/8813/")</param>    
        public void MoveDirFile(string sourceFileName)
        {
            try
            {
                int lastIndex = sourceFileName.LastIndexOf('\\');
                string sourcePath = sourceFileName.Substring(0, lastIndex).Replace("CN", "CN_back");
                string newPath = sourcePath + "\\" + sourceFileName.Substring(lastIndex + 1);
                if (!Directory.Exists(sourcePath))
                {
                    Directory.CreateDirectory(sourcePath);
                }
                if (File.Exists(newPath))
                {
                    File.Delete(newPath);
                }
                File.Move(sourceFileName, newPath);
            }
            catch (Exception ex)
            {

            }


        }


        /// <summary>
        /// 根据文件路径path获取解析后的html模板
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public IHtmlDocument GetProxyHtml(string path)
        {
            //return new JumonyParser().LoadDocument(url, System.Text.Encoding.GetEncoding("utf-8"));

            if (string.IsNullOrWhiteSpace(path))
                path = @"C:\notice_list.txt";
            StreamReader sr = new StreamReader(path);
            var str = "";
            string content;
            while ((content = sr.ReadLine()) != null)
            {
                str += content.ToString();
            }
            sr.Dispose();
            return new JumonyParser().Parse(str);
        }
        /// <summary>
        /// 解析Html，返回单条数据
        /// </summary>
        /// <returns></returns>
        public Cars GetCarsByHtml(IHtmlDocument dom)
        {
            var car = new Cars();
            var carinfo = new CN357_CarInfo();
            var eninfo = new CN357_EngineInfo();
            //解析Html
            var carTable = dom.Find("table").FirstOrDefault();
            var trs = carTable.Find("tr");//tr集合
            var trIndex = 0;

            foreach (var tr in trs)
            {
                trIndex += 1;

                //第1行，变更扩展批次
                if (trIndex == 1)
                {
                    var td2 = tr.Find("td:nth-child(2)");
                    //a标签内是扩展的批次，拼接一个a标签字符串存进去
                    var spanA = td2.Find("a");
                    var recordLotStr = "";
                    foreach (var a in spanA)
                    {
                        recordLotStr += a.InnerText() + ",";
                    }
                    //去掉批次最后一位逗号间隔符
                    if (!string.IsNullOrWhiteSpace(recordLotStr))
                        recordLotStr = recordLotStr.Substring(0, recordLotStr.Length - 1);
                    carinfo.ExtendRecord = recordLotStr;
                    continue;
                }
                //第2行 公告型号，公告批次
                if (trIndex == 2)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.NoticeSeries = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.NoticeLot = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //第3行 品牌、种类
                if (trIndex == 3)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.CarBrand = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.CarType = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //第4行 额定质量  总质量
                if (trIndex == 4)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.QualityRated = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.QualityTotal = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //第5行 整备质量  燃料种类
                if (trIndex == 5)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.CurbWeight = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.FuelType = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //第6行 排放依据标准 轴数
                if (trIndex == 6)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.EmissionStandard = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.AxleCount = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //第7行  轴距  轴荷
                if (trIndex == 7)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.AxleBase = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.AxleWeight = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //第8行 弹簧片数 轮胎数
                if (trIndex == 8)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.SpringCount = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.TyreCount = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //第9行 轮胎规格  接近离去角
                if (trIndex == 9)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.TyreSpecification = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.Angles = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //第10行 前悬后悬   前轮距
                if (trIndex == 10)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.Overhang = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.TrackFront = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //line 11 后轮距  识别代号
                if (trIndex == 11)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.TrackRear = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.VIN = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //line 12 整车长 整车宽
                if (trIndex == 12)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.CarLength = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.CarWidth = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //line13  整车高 货厢长
                if (trIndex == 13)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.CarHeight = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.BodyLength = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //line14 货厢宽  货厢高
                if (trIndex == 14)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.BodyWidth = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.BodyHeight = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //line15 最高车速  额定载客
                if (trIndex == 15)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.MaxSpeed = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.PassengerRated = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //line16 驾驶室准乘人数  转向形式
                if (trIndex == 16)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.CabPass = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.TurnType = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //line17 准拖挂车总质量  载质量利用系数
                if (trIndex == 17)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.TrailerQuality = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.UsageQuality = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //line18 半挂车鞍座最大承载质量   企业名称
                if (trIndex == 18)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.SaddleQuality = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.CompanyName = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //line19 企业地址  电话号码
                if (trIndex == 19)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.CompanyAddress = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.PhoneNumber = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //line20 传真号码   邮政编码
                if (trIndex == 20)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.CompanyFax = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.PostCode = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //line21 底盘1 底盘2
                if (trIndex == 21)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.Underpan1 = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.Underpan2 = td4 != null ? td4.InnerText() : "";
                    continue;
                }
                //line22 底盘3 底盘4
                if (trIndex == 22)
                {
                    var td2 = tr.Find("td:nth-child(2)").FirstOrDefault();
                    carinfo.Underpan3 = td2 != null ? td2.InnerText() : "";
                    var td4 = tr.Find("td:last-child").FirstOrDefault();
                    carinfo.Underpan4 = td4 != null ? td4.InnerText() : "";
                    continue;
                }
            }

            //备注: 最后一行 
            var lastTr = trs.LastOrDefault();
            var remarkTd = lastTr.Find("td:nth-child(2)").FirstOrDefault();
            carinfo.Remark = remarkTd != null ? remarkTd.InnerText() : "";

            //发动机表格
            var enTrs = dom.Find("td table:first-child").Find("tr");//发动机table内的tr集合
            var enLastTr = enTrs.LastOrDefault();
            //有的网页没有发动机项
            if (enLastTr != null && enLastTr.Container != null)
            {
                var enLastTds = enLastTr.Find("td");
                var enIndex = 1;
                foreach (var td in enLastTds)
                {
                    if (enIndex == 1)
                        eninfo.EngineType = td.InnerText();
                    if (enIndex == 2)
                        eninfo.EngineCompany = td.InnerText();
                    if (enIndex == 3)
                        eninfo.EngineTradeMark = td.InnerText();
                    if (enIndex == 4)
                        eninfo.Displacement = td.InnerText();
                    if (enIndex == 5)
                        eninfo.Power = td.InnerText();
                    enIndex += 1;
                }
            }
            car.CarInfo = carinfo;
            car.EngineInfo = eninfo;
            return car;
        }

        /// <summary>
        ///  记录文本日志
        /// </summary>
        /// <param name="type">1为解析模版日志  2为批量插入报错日志</param>
        /// <param name="msg">信息</param>
        public void WriteLog(short type, string msg)
        {
            //创建日志文件夹
            if (!Directory.Exists(this.logBaseDic))
            {
                Directory.CreateDirectory(logBaseDic);
            }
            //模版错误日志
            if (type == 1)
            {
                if (!File.Exists(this.tempLogPath))
                {
                    File.CreateText(tempLogPath).Close();
                }
                StreamWriter sw = File.AppendText(tempLogPath);
                sw.WriteLine(msg);
                sw.Close();
                sw.Dispose();
            }
            //入库错误日志
            if (type == 2)
            {
                if (!File.Exists(this.dbLogPath))
                {
                    File.CreateText(dbLogPath).Close();
                }
                StreamWriter sw = File.AppendText(dbLogPath);
                sw.WriteLine(msg);
                sw.Close();
                sw.Dispose();
            }

        }
    }

    //临时类，存放批次和文件名
    public class CarInfoFileModel
    {
        /// <summary>
        /// 文件名称
        /// </summary>
        public string FileName { get; set; }
        /// <summary>
        /// 文件路径
        /// </summary>
        public string FilePath { get; set; }
        /// <summary>
        /// 外层文件夹名称
        /// </summary>
        public int FolderName { get; set; }
    }
    //临时类 存放车辆信息和发动机信息
    public class Cars
    {
        public CN357_CarInfo CarInfo { get; set; }
        public CN357_EngineInfo EngineInfo { get; set; }
    }
}
